package baseFx.common.config.impl;

import baseFx.common.Env;
import baseFx.common.Stream;
import baseFx.common.config.ConfigReader;
import baseFx.common.utils.ExceptionUtils;
import baseFx.common.utils.StringUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class PropertiesFileReader implements ConfigReader {
    private String configPath;
    private final Map<String, String> data = new HashMap<>();

    public PropertiesFileReader() {
        this(null);
    }

    public PropertiesFileReader(String path) {
        configPath = path == null ? "application" : path;
        try {
            load();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void load() throws FileNotFoundException {
        String path = configPath;
        InputStream stream = null;
        if (path.toLowerCase().endsWith("properties") == false) {
            path += ".properties";
        }
        String full = path.replace("/", Env.fileSeparator());
        if (new File(full).exists()) {
            stream = new FileInputStream(full);
            configPath = new File(full).getPath();
        }
        if (stream == null && Env.getMainClass() != null && path.startsWith("/")) {
            full = (StringUtils.trimRight(Env.appDir(), Env.fileSeparator()) + path).replace("/", Env.fileSeparator());
            if (new File(full).exists()) {
                stream = new FileInputStream(full);
                configPath = new File(full).getPath();
            }
        }
        if (stream == null && Env.userDir() != null && path.startsWith("/")) {
            full = (StringUtils.trimRight(Env.userDir(), Env.fileSeparator()) + path).replace("/", Env.fileSeparator());
            if (new File(full).exists()) {
                stream = new FileInputStream(full);
                configPath = new File(full).getPath();
            }
        }
        if (stream == null) {
            stream = getClass().getResourceAsStream(path);
        }
        if (stream == null) {
            return;
        }
        try (InputStream sm = stream) {
            Properties properties = new Properties();
            try (InputStreamReader reader = new InputStreamReader(sm, StandardCharsets.UTF_8)) {
                properties.load(reader);
                data.clear();
                for (String name : properties.stringPropertyNames()) {
                    data.put(name.toLowerCase(), properties.getProperty(name));
                }
            }
        } catch (Exception e) {
            throw ExceptionUtils.toRuntime(e);
        }
    }

    @Override
    public String read(String namespace, String name) {
        if (namespace != null && namespace.length() > 0) {
            name = namespace + "." + name;
        }
        name = name.toLowerCase();
        if (data.containsKey(name)) {
            return data.get(name);
        }
        return null;
    }

    @Override
    public List<String> getNames(String namespace) {
        if (StringUtils.hasValue(namespace)) {
            String find = namespace.toLowerCase() + ".";
            return Stream.create(data.keySet()).filter(i -> i.startsWith(find)).map(i -> i.substring(find.length())).toList();
        } else {
            return new ArrayList<>();
        }
    }

    @Override
    public void reload() {
        data.clear();
        try {
            load();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

